package com.xbh.management.service;

import com.xbh.common.constants.FileType;
import io.minio.MinioClient;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@Component
public class MinioService {
    private static Logger logger = LoggerFactory.getLogger(MinioService.class);

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.host}")
    private String fileUrl;

    @Value("${minio.bucket}")
    private String bucket;

    public String minioPath() {
        String responseStr = fileUrl + "/" + bucket + "/";
        return responseStr;
    }

    public void putObject(String fileName, Workbook workBook) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workBook.write(outputStream);
        workBook.close();
        outputStream.flush();
        outputStream.close();
        putObject(fileName, outputStream, FileType.XLSX);
    }

    public String putObject(String fileName, String fileBase64, String fileType) {
        String responseStr = "";
        try {
            byte[] decode = Base64.getDecoder().decode(fileBase64);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            outputStream.write(decode);
            outputStream.flush();
            byte[] fileByte = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(fileByte);
            minioClient.putObject(bucket, fileName, inputStream, fileByte.length, getContentType(fileType));
            responseStr = fileUrl + "/" + bucket + "/" + fileName;
        } catch (Exception e) {
            logger.error("上传文件失败", e);
            Assert.notNull(null, "S#上传文件失败");
        }
        return responseStr;
    }

    public void putObject(String fileName, byte[] fileByte, String fileType) throws Exception {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(fileByte);
        minioClient.putObject(bucket, fileName, inputStream, fileByte.length, getContentType(fileType));
    }

    public String getUrl(String fileName) {
        return fileUrl + "/" + bucket + "/" + fileName;
    }

    /**
     *
     * @param fileName
     * @return
     */
    public String getStrObject(String fileName) {
        String str = null;
        try {
            InputStream stream = minioClient.getObject(bucket, fileName);
            byte[] buf = new byte[16384];
            int bytesRead;
            StringBuffer line = new StringBuffer();
            while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
                line.append(new String(buf, 0, bytesRead));
            }
            str = line.toString();
            stream.close();
        } catch (Exception e) {
            logger.error("文本文件下载读取失败", e);
            Assert.notNull(null, "S#文本文件下载读取失败");
        }
        return str;
    }

    /**
     * 上传文本到minio
     *
     * @param str
     * @param fileName
     */
    public String putStrObject(String str, String fileName) {
        String responseStr = "";
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(str.getBytes("UTF-8"));
            Map<String, String> headerMap = new HashMap<>();
            headerMap.put("Content-Type", "application/octet-stream");
            minioClient.putObject(bucket, fileName, bais, bais.available(), headerMap);
            bais.close();
            responseStr = fileUrl + "/" + bucket + "/" + fileName;
        } catch (Exception e) {
            logger.error("上传文本文件失败", e);
            Assert.notNull(null, "S#上传文本文件失败");
        }
        return responseStr;
    }

    /**
     * 上传文本文件
     * @param fileName
     * @param outputStream
     * @param fileType
     * @return
     */
    public String putObject(String fileName, ByteArrayOutputStream outputStream, String fileType) {
        try {
            byte[] fileByte = outputStream.toByteArray();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(fileByte);
            minioClient.putObject(bucket, fileName, inputStream, fileByte.length, getContentType(fileType));
        } catch (Exception e) {
            logger.error("上传文本文件失败", e);
            Assert.notNull(null, "S#上传文本文件失败");
        }
        return getUrl(fileName);
    }

    /** 下载文本文件
     * @param fileName
     * @return
     */
    public InputStream getObject(String fileName) {
        InputStream file = null;
        try {
            //根据文件名称获取文件转为XSSFWorkbook 文件
            file = minioClient.getObject(bucket, fileName);
        } catch (Exception e) {
            logger.error("下载文件失败", e);
            Assert.notNull(null, "S#下载文件失败");
        }
        return file;
    }

    /**
     * 判断文本类型
     * @param fileType
     * @return
     */
    private String getContentType(String fileType) {
        if (FileType.JPG.equalsIgnoreCase(fileType) || FileType.JPEG.equalsIgnoreCase(fileType) || FileType.JPE.equalsIgnoreCase(fileType)) {
            return "image/jpeg";
        } else if (FileType.PNG.equalsIgnoreCase(fileType)) {
            return "image/png";
        } else if (FileType.XLSX.equalsIgnoreCase(fileType)) {
            return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        } else if (FileType.XLS.equalsIgnoreCase(fileType)) {
            return "application/vnd.ms-excel";
        } else if (FileType.DOCX.equalsIgnoreCase(fileType)) {
            return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
        } else if (FileType.DOC.equalsIgnoreCase(fileType)) {
            return "application/msword";
        } else if (FileType.PDF.equalsIgnoreCase(fileType)) {
            return "application/pdf";
        } else if (FileType.ZIP.equalsIgnoreCase(fileType)) {
            return "application/x-zip-compressed";
        } else if (FileType.RAR.equalsIgnoreCase(fileType)) {
            return "application/octet-stream";
        } else {
            Assert.notNull(null, "S#未知文件类型");
            return null;
        }
    }
}
